package com.ta.gulimall.product.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ta.gulimall.common.view.to.SkuFullReductionTo;
import com.ta.gulimall.common.utils.system.PageUtils;
import com.ta.gulimall.common.utils.system.Query;
import com.ta.gulimall.product.dao.SkuInfoDao;
import com.ta.gulimall.product.feign.CouponFeignService;
import com.ta.gulimall.product.service.*;
import com.ta.gulimall.product.view.entity.SkuImagesEntity;
import com.ta.gulimall.product.view.entity.SkuInfoEntity;
import com.ta.gulimall.product.view.entity.SkuSaleAttrValueEntity;
import com.ta.gulimall.product.view.entity.SpuInfoDescEntity;
import com.ta.gulimall.product.view.pto.SpuDto;
import com.ta.gulimall.product.view.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

@Service("skuInfoService")
public class SkuInfoServiceImpl  extends ServiceImpl<SkuInfoDao, SkuInfoEntity> implements SkuInfoService {
    @Autowired
    SkuSaleAttrValueService skuSaleAttrValueService;
    @Autowired
    SkuImagesService skuImagesService;
    @Autowired
    CouponFeignService couponFeignService;
    @Autowired
    SpuInfoService spuInfoService;
    @Autowired
    SpuInfoDescService spuInfoDescService;
    @Autowired
    ProductAttrValueService productAttrValueService;
    @Autowired
    ThreadPoolExecutor poolExecutor;
    @Override
    public void saveSkuInfo(SpuDto spuDto, List<Skus> skus) {
        if (CollUtil.isEmpty(skus)){
            throw new RuntimeException("skus商品信息是空的");
        }

        skus.forEach(sku -> {
            SkuInfoEntity skuInfo = getSkuInfo(spuDto, sku);
            
            this.save(skuInfo);

            Long skuId = skuInfo.getSkuId();
            skuSaleAttrValueService.saveSkuSaleAttr(skuId, sku.getAttr());

            skuImagesService.saveSkuImages(skuId, sku.getImages());

            SkuFullReductionTo skuFullReductionTo = BeanUtil.copyProperties(sku, SkuFullReductionTo.class).setSkuId(skuId);
            couponFeignService.saveSkuFullReduction(skuFullReductionTo);
        });
    }

    @Override
    public PageUtils pageSkuInfos(Map<String, Object> params) {
        String key = (String) params.get("key");
        String catelogId = (String) params.get("catelogId");
        String brandId = (String) params.get("brandId");

        LambdaQueryWrapper<SkuInfoEntity> wrapper = new LambdaQueryWrapper<SkuInfoEntity>()
                .eq(StrUtil.isNotBlank(catelogId) && !"0".equals(catelogId), SkuInfoEntity::getCatalogId, catelogId)
                .eq(StrUtil.isNotBlank(brandId) && !"0".equals(brandId), SkuInfoEntity::getBrandId, brandId)
                .ge(!StrUtil.equals((String) params.get("min"), "0"), SkuInfoEntity::getPrice, params.get("min"))
                .le(!StrUtil.equals((String) params.get("max"), "0"), SkuInfoEntity::getPrice, params.get("max"))
                .and(StrUtil.isNotBlank(key), eq -> eq.eq(SkuInfoEntity::getSkuId, key).or().like(SkuInfoEntity::getSkuName, key));
        IPage<SkuInfoEntity> page = this.page(new Query<SkuInfoEntity>().getPage(params), wrapper);

        return new PageUtils(page);
    }

    @Override
    public List<SkuInfoEntity> listSkuInfo(Long spuId) {
        LambdaQueryWrapper<SkuInfoEntity> wrapper = new LambdaQueryWrapper<SkuInfoEntity>()
                .eq(SkuInfoEntity::getSpuId, spuId);
        List<SkuInfoEntity> skuList = list(wrapper);
        return skuList;
    }

    @Override
    public SkuItemVo getSkuItem(Long skuId) {
        SkuItemVo skuItemVo = new SkuItemVo();
        CompletableFuture<SkuInfoEntity> SkuInfoFuture = CompletableFuture.supplyAsync(() -> {
            SkuInfoEntity skuInfo = getById(skuId);
            skuItemVo.setInfo(skuInfo);
            return skuInfo;
        }, poolExecutor);

        CompletableFuture<Void> ImagesFuture = CompletableFuture.runAsync(() -> {
            List<SkuImagesEntity> imagesEntities = skuImagesService.listBySkuId(skuId);
            skuItemVo.setImages(imagesEntities);
        }, poolExecutor);

        CompletableFuture<Void> descFuture = SkuInfoFuture.thenAcceptAsync(sku -> {
            SpuInfoDescEntity descEntity = spuInfoDescService.getById(sku.getSpuId());
            skuItemVo.setDesp(descEntity);
        }, poolExecutor);

        CompletableFuture<Void> saleAttrFuture = SkuInfoFuture.thenAcceptAsync(sku -> {
            List<SkuItemSaleAttrsVo> skuItemSaleAttrsVos = skuSaleAttrValueService.listSaleAttrBySpuId(sku.getSpuId());
            skuItemVo.setSaleAttrs(skuItemSaleAttrsVos);
        }, poolExecutor);

        CompletableFuture<Void> baseAttrFuture = SkuInfoFuture.thenAcceptAsync(sku -> {
            List<SpuGroupBaseAttrVo> spuGroupBaseAttrVos = productAttrValueService.listBaseAttrsWithGroup(sku.getSpuId(), sku.getCatalogId());
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            skuItemVo.setBaseAttrs(spuGroupBaseAttrVos);
        }, poolExecutor);

        try {
            CompletableFuture.allOf(ImagesFuture, descFuture, saleAttrFuture, baseAttrFuture).get();
        } catch (InterruptedException | ExecutionException ignored) {
            throw new RuntimeException(ignored.getMessage(), ignored);
        }
        return skuItemVo;
    }

    @Override
    public List<String> getSkuAttr(Long skuId) {
        List<SkuSaleAttrValueEntity> list = skuSaleAttrValueService.list(new LambdaQueryWrapper<SkuSaleAttrValueEntity>().eq(SkuSaleAttrValueEntity::getSkuId, skuId));
        List<String> collect = list.stream().map(m -> m.getAttrName() + ":" + m.getAttrValue()).collect(Collectors.toList());
        return collect;
    }

    @Override
    public Map<Long, Long> listSpuIdBySkuIds(List<Long> skuIds) {
        Map<Long, SkuInfoEntity> entityMap = baseMapper.listSpuIdBySkuIds(skuIds);
        return entityMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, v -> v.getValue().getSpuId()));
    }

    @Override
    public List<SkuInfoEntity> querySpuInfo(List<Long> skuIds) {
        return listByIds(skuIds);
    }

    private SkuInfoEntity getSkuInfo(SpuDto spuDto, Skus sku) {
        SkuInfoEntity skuInfo = BeanUtil.copyProperties(sku, SkuInfoEntity.class);
        skuInfo.setSkuDesc(sku.getDescar().stream().collect(Collectors.joining(",")));
        skuInfo.setCatalogId(spuDto.getCatalogId());
        skuInfo.setBrandId(spuDto.getBrandId());
        skuInfo.setSpuId(spuDto.getSpuId());
        skuInfo.setSkuDefaultImg(sku.getImages().stream().filter(f -> f.getDefaultImg() == 0).map(Images::getImgUrl).findFirst().orElse(null));
        return skuInfo;
    }
}
